// SPDX-License-Identifier: GPL-2.0-only
/*
 * Example code for CSV RTMR & ATTESTATION.
 *
 * Copyright (C) 2025 Hygon Info Technologies Ltd.
 *
 * Author: Liyang Han <hanliyang@hygon.cn>
 */

#ifndef __CSV_ATTESTATION_H__
#define __CSV_ATTESTATION_H__

#include "csv-guest-module-tool.h"
#include "hygoncert.h"
#include "rtmr.h"

#define SM3_HASH_BLOCK_SIZE			32U
#define VM_ID_SIZE				16U
#define VM_VERSION_SIZE				16U
#define REPORT_USER_DATA_SIZE			64U
#define REPORT_MNONCE_SIZE			16U
#define PEK_CERT_SIZE				HYGON_CSV_CERT_SIZE
#define SN_SIZE					64U
#define SEALING_KEY_SIZE			32U

#define CSV_ATTESTATION_TEE_INFO_SIZE		0x150U
#define CSV_ATTESTATION_TEE_INFO_SIGN_SIZE	0xB4U
#define CSV_ATTESTATION_REPORT_SIZE		0x9F4U

#define CSV3_ATTESTATION_TEE_INFO_EXT_SIZE	0x490U
#define CSV3_ATTESTATION_TEE_INFO_EXT_SIGN_SIZE	0x400U
#define CSV3_ATTESTATION_REPORT_EXT_SIZE	0x1000U

#define CSV_ATTESTATION_REPORT_OUT_FILE		"report.bin"

typedef uint8_t sm3_hash_block_t[SM3_HASH_BLOCK_SIZE];

/**
 * structures for CSV attestation report.
 *
 * This is also referenced as legacy attestation. In the legacy attestation, the
 * suze if the tee_info in the report is 0x150 (see structure
 * csv_attestation_report). The tee_info does not contain rtmr.
 */

typedef struct csv_attestation_tee_info {
	sm3_hash_block_t	user_pubkey_digest;
	uint8_t			vm_id[VM_ID_SIZE];
	uint8_t			vm_version[VM_VERSION_SIZE];
	uint8_t			user_data[REPORT_USER_DATA_SIZE];
	uint8_t			mnonce[REPORT_MNONCE_SIZE];
	sm3_hash_block_t	measure;
	uint32_t		policy;
	uint32_t		sig_usage;
	uint32_t		sig_algo;
	uint32_t		anonce;
	union {
		uint8_t			sig1[144];
		hygon_signature_t	ecc_sig1;
	};
} __attribute__((packed)) csv_attestation_tee_info_t;

typedef csv_attestation_tee_info_t csv3_attestation_tee_info_t;

typedef struct csv_attestation_report {
	csv_attestation_tee_info_t	tee_info;
	uint8_t				pek_cert[PEK_CERT_SIZE];
	uint8_t				chip_id[SN_SIZE];
	uint8_t				sealing_key[SEALING_KEY_SIZE];
	sm3_hash_block_t		sm3_hmac;
} __attribute__((packed)) csv_attestation_report_t;

typedef csv_attestation_report_t csv3_attestation_report_t;

/**
 * the user space input buffer for legacy attestation.
 *
 * struct csv_guest_user_data_attestation - ATTESTATION command parameters.
 *
 *	In the legacy attestation, the size of tee_info portion of the
 *	attestation report is 0x150. The tee_info does not contain rtmr.
 *
 * @user_data: user defined data, it's suggest that contains challenge data
 *	       from the relying party.
 * @mnonce: user's random nonce, just for anti-replay attack protection.
 * @hash: the sm3 hash of the @user_data and @mnonce.
 */
typedef struct csv_guest_user_data_attestation {
	uint8_t			user_data[REPORT_USER_DATA_SIZE];	/* In */
	uint8_t			mnonce[REPORT_MNONCE_SIZE];		/* In */
	sm3_hash_block_t	hash;					/* In */
} __attribute__((packed)) csv_guest_user_data_attestation_t;

/**
 * structure for CSV3 attestation report that support extensions.
 *
 * This is also referenced as extended attestation. In the extended attestation,
 * the size of the tee_info in the report is 0x490 (see structure
 * csv3_attestation_tee_info_ext). The tee_info contains rtmr by default.
 */

typedef struct csv3_attestation_tee_info_ext {
	sm3_hash_block_t	user_pubkey_digest;
	uint8_t			vm_id[VM_ID_SIZE];
	uint8_t			vm_version[VM_VERSION_SIZE];
	uint8_t			user_data[REPORT_USER_DATA_SIZE];
	uint8_t			mnonce[REPORT_MNONCE_SIZE];
	sm3_hash_block_t	measure;
	uint32_t		policy;
	uint32_t		sig_usage;
	uint32_t		sig_algo;
	uint32_t		build;
	uint16_t		rtmr_version;
	uint8_t			reserved0[14];
	uint8_t			rtmr[CSV_RTMR_REG_SIZE * CSV_RTMR_REG_NUM];
	uint8_t			reserved1[656];
	union {
		uint8_t			sig1[144];
		hygon_signature_t	ecc_sig1;
	};
} __attribute__((packed)) csv3_attestation_tee_info_ext_t;

typedef struct csv3_attestation_report_ext {
	csv3_attestation_tee_info_ext_t	tee_info;
	uint8_t				pek_cert[PEK_CERT_SIZE];
	uint8_t				chip_id[SN_SIZE];
	uint8_t				sealing_key[SEALING_KEY_SIZE];
	sm3_hash_block_t		sm3_hmac;
	uint8_t				reserved[716];
} __attribute__((packed)) csv3_attestation_report_ext_t;

#define CSV_ATTESTATION_MAGIC_LEN		16U
#define CSV_ATTESTATION_MAGIC_STRING		"ATTESTATION_EXT"

#define CSV_ATTESTATION_FLAG_REPORT_EXT_BIT	0
#define CSV_ATTESTATION_FLAG_REPORT_EXT		(1U << CSV_ATTESTATION_FLAG_REPORT_EXT_BIT)

typedef uint8_t attestation_magic[CSV_ATTESTATION_MAGIC_LEN];

/**
 * the user space input buffer for extended attestation.
 *
 * struct csv_guest_user_data_attestation_ext - ATTESTATION command parameters.
 *
 *	In the extended attestation, the size of tee_info portion of the
 *	attestation report is 0x490. The tee_info contains rtmr by default.
 *
 *	Currently, the extended attestation only supported for CSV3 guest.
 *
 * @user_data: user defined data, it's suggest that contains challenge data
 *	       from the relying party.
 * @mnonce: user's random nonce, just for anti-replay attack protection.
 * @hash: the sm3 hash of the @user_data and @mnonce.
 * @magic: The magic string indicates this is an extended attestation aware
 *	   request. Due to historical reasons, users always provide a buffer
 *	   that is much larger than the size of structure
 *	   csv_guest_user_data_attestation_ext. The magic string will be used to
 *	   determine whether the user space uses the extended attestation aware
 *	   request. If the user space is using such a request, the flags field
 *	   will be used to indicate the format of the attestation report.
 * @flags: the bit flags used to indicate how to extend the attestation report.
 */
typedef struct csv_guest_user_data_attestation_ext {
	uint8_t			user_data[REPORT_USER_DATA_SIZE];	/* In */
	uint8_t			mnonce[REPORT_MNONCE_SIZE];		/* In */
	sm3_hash_block_t	hash;					/* In */
	attestation_magic	magic;					/* In */
	uint32_t		flags;					/* In */
} __attribute__((packed)) csv_guest_user_data_attestation_ext_t;

/**
 * struct csv_report_req - Request struct for CSV_CMD_GET_REPORT IOCTL.
 *
 * @report_data: Request and response buffer. When a user requests an
 *		 attestation report, the buffer pointed to by this field is
 *		 referred to as the request buffer. The data in the request
 *		 buffer complies with the `attestation_userdata` or
 *		 `attestation_userdata_ext` structure. When the request is
 *		 returned, the buffer pointed to by this field is refereed to as
 *		 the response buffer, the data in the response buffer complies
 *		 with `csv_attestation_report` or `csv3_attestation_report_ext`
 *		 structure.
 * @len: Length of the user buffer.
 * @reserved: Padding the structure to 16 bytes.
 */
struct csv_report_req {
        __u64 report_address;
        __u32 len;
	__u32 reserved;
} __attribute__((packed));

/**
 * CSV_CMD_GET_REPORT - Get ATTESTATION REPORT of the Hygon CSV Guest.
 *
 * Return 0 on success, -EIO on firmware failure, and standard errno on other
 * general error cases.
 */
#define CSV_CMD_GET_REPORT      _IOWR('D', 1, struct csv_report_req)

CHECK_STRUCT_SIZE(csv_attestation_tee_info_t, CSV_ATTESTATION_TEE_INFO_SIZE);
CHECK_STRUCT_SIZE(csv_attestation_report_t, CSV_ATTESTATION_REPORT_SIZE);

CHECK_STRUCT_SIZE(csv3_attestation_tee_info_ext_t, CSV3_ATTESTATION_TEE_INFO_EXT_SIZE);
CHECK_STRUCT_SIZE(csv3_attestation_report_ext_t, CSV3_ATTESTATION_REPORT_EXT_SIZE);

int handle_subcmd_attestation(int argc, char *argv[]);

#endif  /* __CSV_ATTESTATION_H__ */
